/*
 * NiceValidate JavaScript Library v1.0.0
 * Date: 2017-07-24
 * author: wxq
 */
(function (name, context, factory) {
    // AMD ,Node ,browser context
    if (typeof module !== "undefined" && module.exports) {
        module.exports = factory();
    } else if (typeof define === "function" && define.amd) {
        define(factory);
    } else context[name] = factory();

})("NiceValidate",typeof window !== "undefined" ? window : this, function () {
    const defaultErrStyle = {
        color:"#a94442",
        size:"12px",
        nullErr:"不能为空.",
        rangeErr:"长度在1-25个字符之间.",
        emailErr:"the email is invalid.",
        phoneErr:"the phone is invalid.",
        numberErr:"必须为数字.",
        cardErr:"the card is invalid.",
        cnErr:"the char is invalid",
        dateErr:"the date is invalid."
    };
    let reValue = {};

    function NiceValidate() {
        //set global data
        this.globalArg = arguments[0];

        /**
         * execute Onblur, Immediate execution function
         */
        (function implOnblur(arg,ctx) {
            try {
                for(let i = 0;i< arg.length; i++){
                    ctx.bindOnblur(arg[i])
                }
            }catch (err){
                console.log(err)
            }

        })(this.globalArg,this);

        /**
         * user use this method to validate
         * @returns {*}
         */
        this.niceValidate = function () {
            reValue = {};
            let flag = [];
            for(let i = 0 ; i < this.globalArg.length ; i++){
                if(this.globalArg[i].dom){
                    flag.push(this.setError(this.globalArg[i]));
                }else {
                    throw new Error("the dom is not defined")
                }
            }
            for(let j = 0 ; j < flag.length ;j++){
                if(!flag[j].flag){
                    return false
                }else {
                    for(let item in flag[j]){
                        if(item !== "flag") {
                            reValue[item] = flag[j][item]
                        }
                    }
                }
            }
            return reValue;
        }
    }

    NiceValidate.prototype = {
        constructor:NiceValidate,

        /**
         * bind onblur
         * @param arg
         */
        bindOnblur : function (arg) {
            arg.dom.onblur = ()=> {
                return this.setError(arg);
            }
        },

        /**
         * add err dom
         * @param arg
         * @param errInfo
         * @param def
         * @returns {{}}
         */
        insertAfter : function(arg,errInfo,def){
            let currentDom = document.createElement("span");
            let valueObj = {};
            //set id and class.
            currentDom.setAttribute("class","err-info");
            currentDom.setAttribute("id","err-"+arg.dom.id);

            // set default err content and border color if do not existed.
            arg.dom.style.borderColor = arg.color ? arg.color : defaultErrStyle.color;
            currentDom.style.color = arg.color ? arg.color : defaultErrStyle.color;
            currentDom.style.fontSize = arg.color ? arg.color : defaultErrStyle.size;
            currentDom.innerHTML = errInfo ? errInfo : def;

            let parent = arg.dom.parentNode;
            if (parent.lastChild === arg.dom) {
                parent.appendChild(currentDom);
            } else {
                parent.insertBefore(currentDom, arg.dom.nextSibling);
            }
            valueObj[arg.dom.id] = arg.dom.value;
            valueObj['flag'] = false;
            return valueObj
        },


        /**
         * show dom
         * @param arg
         * @returns {*}
         */
        setError : function (arg) {
            const errDom = document.querySelector("#err-"+arg.dom.id);
            let valueObj = {};
            if(errDom){
                errDom.parentNode.removeChild(errDom);
                arg.dom.style.borderColor = "";
            }
            //if null
            if(!arg.isNull && arg.isNull !== "undefined"){
                if(!arg.dom.value){
                    return this.insertAfter(arg,arg.nullErr,defaultErrStyle.nullErr);
                }
            }
            //if range invalid
            if(arg.range && arg.dom.value !== ""){
                if(arg.range[0] <= arg.range[1] && arg.range[0] >= 0 && arg.range[1] > 0 && arg.range.length === 2){
                    if(arg.dom.value.length < arg.range[0] || arg.dom.value.length > arg.range[1]) {
                        return this.insertAfter(arg,arg.rangeErr,defaultErrStyle.rangeErr)
                    }
                }else {
                    throw new Error("the 'range' is invalid")
                }
            }
            switch (arg.type){
                case "email":
                    if(!this.ev_email(arg.dom.value)){
                        return this.insertAfter(arg,arg.emailErr,defaultErrStyle.emailErr)
                    }
                    break;
                case "phone":
                    if(!this.ev_phone(arg.dom.value)){
                        return this.insertAfter(arg,arg.phoneErr,defaultErrStyle.phoneErr)
                    }
                    break;
                case "card":
                    if(!this.ev_card(arg.dom.value)){
                        return this.insertAfter(arg,arg.cardErr,defaultErrStyle.cardErr)
                    }
                    break;
                case "date":
                    if(!this.ev_date(arg.dom.value)){
                        return this.insertAfter(arg,arg.dateErr,defaultErrStyle.dateErr)
                    }
                    break;
                case "number":
                    if(!this.ev_number(arg.dom.value)){
                        return this.insertAfter(arg,arg.numberErr,defaultErrStyle.numberErr)
                    }
                    break;
                case "cn":
                    if(!this.ev_cn(arg.dom.value)){
                        return this.insertAfter(arg,arg.cnErr,defaultErrStyle.cnErr)
                    }
                    break;
                default:
                    break
            }
            valueObj[arg.dom.id] = arg.dom.value;
            valueObj['flag'] = true;
            return valueObj
        },

        /**
         *
         * @param email
         * @returns {boolean}
         */
        ev_email:function (email) {
            const reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z]{2,3})+$/;
            const re = new RegExp(reg);
            return re.test(email)
        },

        /**
         *
         * @param phone
         * @returns {boolean}
         */
        ev_phone:function (phone) {
            const reg = /^1(3|4|5|7|8)\d{9}$/;
            const re = new RegExp(reg);
            return re.test(phone)
        },

        /**
         *
         * @param card
         * @returns {boolean}
         */
        ev_card:function (card) {
            const reg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/;
            const re = new RegExp(reg);
            return re.test(card)
        },

        /**
         *
         * @param date
         * @returns {boolean}
         */
        ev_date:function (date) {
            const reg =  /^[0-9]{4}-[0-1]?[0-9]{1}-[0-3]?[0-9]{1}$/;
            const re = new RegExp(reg);
            return re.test(date)

        },
        /**
         *
         * @param number
         * @returns {boolean}
         */
        ev_number:function (number) {
            const reg = "^[0-9]*$";
            const re = new RegExp(reg);
            return re.test(number)
        },

        ev_cn:function (cn) {
            const reg =  /^[\u4E00-\u9FA5]+$/;
            return reg.test(cn)

        }
    };
    return NiceValidate;
});